package org.xmeta;

import java.util.Map;

/**
 * 动作监听器。可监控动作执行前后的信息，也可以向动作上下文中注入信息等。
 */
public interface ActionListener {
    /**
     * 动作真正执行前初始化后触发。
     *
     * @param action 动作
     * @param caller 调用动作者
     * @param actionContext 上下文
     * @param params 参数
     * @param executor 执行器
     */
    void onInit(Action action, Object caller, ActionContext actionContext, Map<String, Object> params, ActionListenerExecutor executor) throws Exception;

    /**
     * 动作执行完毕且没有异常时触发。
     *
     * @param action 动作
     * @param caller 动作调用者
     * @param actionContext 上下文
     * @param result 结果
     * @param executor 执行器
     */
    void onSuccess(Action action, Object caller, ActionContext actionContext, Object result, ActionListenerExecutor executor) throws Exception;

    /**
     * 动作执行后发生了异常时触发。
     *
     * @param action 动作
     * @param caller 动作的调用者
     * @param actionContext 上下文
     * @param t 异常
     * @param executor 执行器
     */
    void onException(Action action, Object caller, ActionContext actionContext, Throwable t, ActionListenerExecutor executor) throws Exception;

    /**
     * 模型执行自己的动作前触发。
     *
     * @param thing 模型
     * @param actionName 动作名
     * @param action 动作
     * @param actionContext 上下文
     * @param params 参数
     * @param executor 监听执行器
     *                 @throws Exception 异常
     */
    void onDoAction(Thing thing, String actionName, Action action, ActionContext actionContext, Map<String, Object> params,
                    ActionListenerExecutor executor) throws Exception;

    /**
     * 模型执行自己的动作结束。
     * @param thing 模型
     * @param actionName 动作名
     * @param action 动作
     * @param actionContext 上下文
     * @param params 参数
     * @param executor 执行器
     * @param result 结果
     * @throws Exception 异常
     */
    void onDoActionFinished(Thing thing, String actionName, Action action, ActionContext actionContext,
                            Map<String, Object> params, ActionListenerExecutor executor, Object result) throws Exception;

    /**
     * 返回一个可以标识该监听器的名字。
     *
     * @return 名字
     */
    default String getName(){
        return this.getClass().getName();
    }
}
